﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.Diagnostics;
using System.IO;

using ImageRecognition2.Forms;
using ImageRecognition2.Action;

using LowLevelGraphics;
using LowLevelGraphics.CustomControls;
using CustomDrawnFileDialog;

using OpenFileDialog = CustomDrawnFileDialog.CustomFileDialog;


namespace ImageRecognition2
{
    public class GuiHelper2
    {
        int viewRectWidth, viewRectHeight; // view window width and height

        Size canvasSize = new Size(60, 40);
        HScrollBar hScrollBar1;
        VScrollBar vScrollBar1;
        protected float zoom = 1.0f;
        
        /// <summary>
        /// Used to convert point to canvas - needed when zooming/scrolling
        /// </summary>
        /// <param name="point"></param>
        /// <returns></returns>
        private Point PointToCanvas(Point point)
        {
            Point pt = new Point();
            if (viewRectWidth > canvasSize.Width * zoom)
            {
                pt.X = (int)((float)(point.X - viewRectWidth / 2 + canvasSize.Width * zoom / 2f) / zoom);
                pt.X = Math.Min(Math.Max(pt.X, 1), canvasSize.Width - 1);
            }
            else pt.X = (int)((float)(point.X + hScrollBar1.Value) / zoom);
            if (viewRectHeight > canvasSize.Height * zoom)
            {
                pt.Y = (int)((float)(point.Y - viewRectHeight / 2 + canvasSize.Height * zoom / 2f) / zoom);
                pt.Y = Math.Max(Math.Min(pt.Y, canvasSize.Height - 1), 1);
            }
            else pt.Y = (int)((float)(point.Y + vScrollBar1.Value) / zoom);
            return pt;
        }

        /// <summary>
        /// Used to Convert Point to Control - needed when zooming/scrolling
        /// </summary>
        /// <param name="point"></param>
        /// <returns></returns>
        private Point PointToControl(Point point)
        {
            float xOffset = viewRectWidth > canvasSize.Width * zoom ? (viewRectWidth - canvasSize.Width * zoom) / 2f :
                -hScrollBar1.Value;
            float yOffset = viewRectHeight > canvasSize.Height * zoom ? (viewRectHeight - canvasSize.Height * zoom) / 2f :
                -vScrollBar1.Value;
            Matrix mxCanvastoContol = new Matrix();
            mxCanvastoContol.Scale(zoom, zoom);
            mxCanvastoContol.Translate(xOffset, yOffset, MatrixOrder.Append);
            Point[] pts = new Point[] { point };
            mxCanvastoContol.TransformPoints(pts);
            return pts[0];
        }
    }

    /// <summary>
    /// Some helper functions for the gui
    /// </summary>
    public static class GuiHelper
    {
        public static bool m_bOpenNewChildOnAction = true;
        public static string m_sFileName = string.Empty;
        public static bool m_bUseStandardFileDialog = true;

        public static bool m_bCloneAction = true;

        public static List<ICommand> m_aCommandList = new List<ICommand>(10);

        /// <summary>
        /// This is used to set the EventHandlers
        /// </summary>
        /// <param name="_item"></param>
        /// <param name="_icommand"></param>
        public static void SetEventHandler(ToolStripItem _item, ICommand _icommand)
        {
            _item.Tag = _icommand;
            _item.Enabled = true;
            Debug.WriteLine(_item.Name + " enabled");
            _item.Click += delegate(object sender, EventArgs e)
            {
                ExecuteAction(_item.Tag, EventArgs.Empty);
                if (MainFormSingleton.ActivePictureBox == null) return;
                MainFormSingleton.ActivePictureBox.Invalidate();
                //Debug.WriteLine(_icommand.Description);
            };
        }

        /// <summary>
        /// CommandList
        /// </summary>
        public static List<ICommand> CommandList
        {
            get { return m_aCommandList; }
        }

        /// <summary>
        /// Executes a control EventHandler bound event-Action
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public static void ExecuteAction(object sender, EventArgs e)
        {
            object o = sender;
            //ohne bild passiert nichts
            if (MainFormSingleton.ActivePictureBox == null || MainFormSingleton.ActivePictureBox.BackgroundImage == null)
            {
                Debug.WriteLine("Nothing to execute. ActivePicture Box or BackgroundImage of ActivePictureBox is null");
                return;
            }

            ICommand command = sender as ICommand;
            if (command != null)
            {
                Stopwatch watch = new Stopwatch();
                watch.Start();

                Debug.Write(string.Format("Executing command {0}", command.Description));

                //Todo: ActionTwoSourceFilters is only because of contextmenu, this could be done better.
                if (m_bOpenNewChildOnAction && command.GetType() != typeof(ActionTwoSourceFilters))
                {
                    Bitmap bitmap = (Bitmap)MainFormSingleton.ActivePictureBox.BackgroundImage.Clone();
                    FormChild formChild = CreateNewChild();
                    formChild.pictureBox1.BackgroundImage = bitmap;

                    if (MainFormSingleton.Instance.tileHorizontalAfterActionHorizontalTeilenToolStripMenuItem.Checked)
                    {
                        MainFormSingleton.Instance.LayoutMdi(MdiLayout.TileHorizontal);
                    }
                    if (MainFormSingleton.Instance.tileVerticalAfterActionStripMenuItem.Checked)
                    {
                        MainFormSingleton.Instance.LayoutMdi(MdiLayout.TileVertical);
                    }
                }
                Debug.WriteLine(string.Format("Execution time: {0}", watch.ElapsedTicks));

                //if ()
                {
                    MainFormSingleton.OriginalBitmap = (Bitmap)MainFormSingleton.ActivePictureBox.BackgroundImage.Clone();
                }

                command.Run(sender, e);


                //Clone action and add to command list
                ICommand icommand = null;
                if (m_bCloneAction)
                {
                    try
                    {
                        icommand = (ICommand)command.Clone();
                        m_aCommandList.Add(icommand);
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine(ex.Message);
                    }
                    finally
                    {
                        UnsafeBitmap bitmap = MainFormSingleton.ActivePictureBox.BackgroundImage;
                        bitmap.Dispose();
                        bitmap.Dispose();
                    }
                }

                watch.Stop();

                //this.statusStrip1.Text = string.Format("Needed Time: {0}", watch.ElapsedTicks.ToString());
            }
        }

        /// <summary>
        /// Creates a new Child
        /// </summary>
        /// <returns></returns>
        public static FormChild CreateNewChild()
        {
            FormChild formChild = new FormChild();
            formChild.ContextMenuStrip = MainFormSingleton.Instance.contextMenuStrip1;
            formChild.MdiParent = MainFormSingleton.Instance;
            formChild.WindowState = FormWindowState.Maximized;
            formChild.Show();
            return formChild;
        }

        /// <summary>
        /// Loads the picture.
        /// </summary>
        /// <returns></returns>
        public static bool LoadPicture()
        {
            return LoadPicture(null);
        }

        /// <summary>
        /// Load a picture
        /// </summary>
        /// <param name="_sFileName"></param>
        /// <returns></returns>
        public static bool LoadPicture(string _sFileName)
        {
            SelectablePictureBox pictureBox1 = MainFormSingleton.ActivePictureBox;
            if (pictureBox1 == null)
            {
                return false;
            }

            if (string.IsNullOrEmpty(_sFileName))
            {
                IFileDialog fd = OpenDecodableFileDialog();

                if (fd.ShowDialog() == DialogResult.OK)
                {
                    m_sFileName = fd.FileName;
                }
                else
                {
                    return false;
                }
            }

            if (!string.IsNullOrEmpty(m_sFileName))
            {
                try
                {
                    Image imageFromFile = Image.FromFile(m_sFileName);
                    if (BitmapFunctions.IsIndexed((Bitmap)imageFromFile))
                    {
                        imageFromFile = BitmapFunctions.GetNonIndexedBitmap((Bitmap)imageFromFile);
                    }
                    MainFormSingleton.ActivePictureBox.BackgroundImage = imageFromFile;
                    MainFormSingleton.ActivePictureBox.BackgroundImageLayout = ImageLayout.Zoom;
                    return true;
                }
                catch (Exception ex)
                {
                    if (MainFormSingleton.Instance.automaticToolStripMenuItem.Checked)
                    {
                        Image image = OpenCoded(m_sFileName);
                        MainFormSingleton.ActivePictureBox.BackgroundImage = image;
                        MainFormSingleton.ActivePictureBox.BackgroundImageLayout = ImageLayout.Zoom;
                        return true;
                    }
                    else
                    {
                        MessageBox.Show(String.Format("{0} oder falsches Format", ex.Message));
                    }
                }
            }
            return true;
        }

        /// <summary>
        /// Opens the decodable file dialog.
        /// </summary>
        /// <returns></returns>
        private static IFileDialog OpenDecodableFileDialog()
        {
            return OpenDecodableFileDialog(m_bUseStandardFileDialog);
        }

        /// <summary>
        /// Opens the decodable file dialog.
        /// </summary>
        /// <param name="bUseNormalFile">if set to <c>true</c> [b use normal file].</param>
        /// <returns></returns>
        private static IFileDialog OpenDecodableFileDialog(bool bUseNormalFile)
        {
            if (bUseNormalFile)
            {
                IFileDialog fd = new OpenFileDialogWrapper();
                return fd;
            }
            else
            {
                ICustomFileDialog fd = new OpenFileDialog();
                fd.Filter = "Picture files (*.JPG;*.GIF;*.PNG)\0*.jpg;*.gif;*.png\0Alle Dateien (*.*)\0\0";
                fd.SelectionChanged += new CustomDrawnFileDialog.SelectionChangedEventHandler(ofd_SelectionChanged);
                return fd;
            }
        }

        /// <summary>
        /// Opens the coded.
        /// </summary>
        /// <param name="_sFileName">Name of the _s file.</param>
        /// <returns></returns>
        private static Image OpenCoded(string _sFileName)
        {
            try
            {
                BinaryCoder coder = new BinaryCoder();
                Image image = coder.GetAsImage(_sFileName);

                return image;
            }
            catch (Exception ex)
            {
                MessageBox.Show(String.Format("{0} oder falsches Format", ex.Message));
                return null;
            }
        }

        /// <summary>
        /// Event handler that is called when the user clicks on a file or folder inside the dialog
        /// </summary>
        /// <param name="path">the full path of the currently-selected file</param>
        private static void ofd_SelectionChanged(object sender, SelectionEventArgs e)
        {
            string _sPath = e.FileName;
            // Check the path points to something valid before trying to display the contents
            if (!File.Exists(_sPath)) return;
            if (!Path.HasExtension(_sPath)) return;
            string ext = Path.GetExtension(_sPath).ToLower();
            if (ext == ".jpg" || ext == ".gif" || ext == ".png")
            {
                try
                {
                    MainFormSingleton.ActivePictureBox.BackgroundImage = new Bitmap(_sPath);
                }
                catch (Exception ex)
                {
                    if (MainFormSingleton.Instance.automaticToolStripMenuItem.Checked)
                    {
                        Image image = OpenCoded(_sPath);
                        MainFormSingleton.ActivePictureBox.BackgroundImage = image;
                    }
                }
            }
        }

    }
}
